package com.security.lasys.agent.detector;

import com.google.gson.Gson;
import com.security.lasys.agent.mainprocess.Server;
import com.security.lasys.agent.plugin.Conf;
import com.security.lasys.agent.plugin.PluginConf;
import com.security.lasys.object.DetectorEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Detector extends Thread {

    private boolean runflag = true;

    /**
     * 与server建立连接，发送对象
     */

    Server server;
    Gson gson = new Gson();
//    线程休眠的时间
    int sleepTime = 1;

    long fileLen;
    long newFileLen;

//    读取下一行的内容
    String strLine = "";
    String eventName;
    String sendStr = "";
    HashMap<String,HashMap<String,String>> map;
    HashMap<String,String> regexMap;//正则表达式
    HashMap<String,String> configMap;

    List<DetectorEvent> eventList = new LinkedList<>();

    //保存从xml文件中读出来的内容
    HashMap<String,String> eventAttrs = new HashMap<>();

    Conf conf;
    PluginConf pluginConf;

    File file;
    RandomAccessFile raf = null;
    private Logger log = LoggerFactory.getLogger(this.getClass());

    public Detector(Conf conf,PluginConf pluginConf){
        this.pluginConf = pluginConf;
        this.conf = conf;
        this.init();
        eventName = this.getName();
        server = new Server();
    }

    private void init(){
        this.runflag = true;
        this.map = new HashMap<>();
        this.regexMap = new HashMap<>();
        this.configMap = new HashMap<>();
        this.file = new File(pluginConf.get("config","location"));
        this.fileLen = file.length();
        this.getRules();
    }

    /**
     *
     * 获取xml文件中的正则表达式
     */
    public void getRules(){
        Vector<String> vectors = pluginConf.getSections();
        for (String vector:vectors){
            Vector<String> vector1 = pluginConf.getOptions(vector);

            for (String i : vector1){
                if (i.equals("regexp")){
                    regexMap.put(vector,pluginConf.get(vector,i));
                    HashMap<String,String> map1 = new HashMap<>();
                    for (String j : vector1){
                        if (!j.equals("regexp")){
                            map1.put(j,pluginConf.get(vector,j));
                        }
                    }
                    map.put(vector,map1);
                }
                if (vector.equals("config")){
                    configMap.put(i,pluginConf.get(vector,i));
                }
            }
        }
    }

    @Override
    public void run(){
        try{
            raf = new RandomAccessFile(file,"r");
        }catch (FileNotFoundException e){
            e.printStackTrace();
        }
        /**
         * 与server端建立连接
         *
         */
        while(runflag){
            try{
                TimeUnit.SECONDS.sleep(sleepTime);
            }catch (InterruptedException e1){
                e1.printStackTrace();
            }

            newFileLen = file.length();
            if (newFileLen <= fileLen){
                newFileLen = fileLen;
                try{
                    //在休眠单位时间后再读取
                    TimeUnit.SECONDS.sleep(sleepTime);
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
            }else{
                try{
                    Match();
                }catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (SecurityException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IllegalArgumentException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (NoSuchMethodException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }
        }
    }

    /**
     * 读取文件的新增数据，并且使用正则表达式去匹配
     * @throws IOException
     * @throws SecurityException
     * @throws IllegalArgumentException
     * @throws NoSuchMethodException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    public void Match() throws IOException,SecurityException,
            IllegalArgumentException,NoSuchMethodException,
            IllegalAccessException,InvocationTargetException{
        raf = new RandomAccessFile(file,"r");
        String str = "";
        raf.seek(fileLen);

        str = raf.readLine();
        log.info("产生的新日志为： " + str );
        while(str != null && str != ""){
            strLine = strLine + str + "\n";
            str = raf.readLine();
            if (MatchRule(str)){
                strLine = "";
            }
        }
        /**
         * 将消息发送出去，并且清空数据链
         */
        if (eventAttrs.size() >= 1){
            sendStr = gson.toJson(eventAttrs);
            server.sendEvent(sendStr);
            eventAttrs = new LinkedHashMap<>();
        }
        fileLen = newFileLen;
    }

    public void runStop(){
        this.runflag = false;
    }

    /**
     *
     * @param str
     * @return
     * @throws IOException
     * @throws SecurityException
     * @throws IllegalArgumentException
     * @throws NoSuchMethodException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    public boolean MatchRule(String str) throws IOException,SecurityException,
            IllegalArgumentException,NoSuchMethodException,
            IllegalAccessException,InvocationTargetException{
        Set<String> rules = regexMap.keySet();
        String rule;
        boolean flag = false;


        eventAttrs.put("type",pluginConf.get("conf","type"));
        for (String regexName : rules){
            rule = regexMap.get(regexName);
            Pattern pattern = Pattern.compile(rule);
            Matcher m = pattern.matcher(str);
            if (m.find()){
//                System.out.println(m.group(1));
                flag = true;
//                判断日志的类型,以及获取各个有意义的字段
                if (pluginConf.get("config","type").equals("detector")){
                    for (String name:map.get(regexName).keySet()){
                        String temp = map.get(regexName).get(name);
                        char[] chars = temp.toCharArray();
                        int t ;
                        if (chars[0] < '0' || chars[0] > '9'){
//                            System.out.println(temp);
                            eventAttrs.put("EVENTTYPE",temp);
                        }else {
                            if (temp.length() == 2) {
                                t = (chars[0] - '0') * 10 + chars[1] - '0';
                            } else {
                                t = chars[0] - '0';
                            }
//                             log.info(t);
                            eventAttrs.put(name, m.group(t));
                            // log.info(event.eventAttrs);
                            // break;
                        }
                    }
                    System.out.println(eventAttrs);
                }
            }
        }
        return flag;
    }

    public static void main(String[] args) {
        Conf conf = new Conf("./config/agent-config.xml");
        PluginConf pluginConf = new PluginConf("./config/webserver.xml");
        Detector detector = new Detector(conf,pluginConf);
        detector.getRules();
        for (String line : detector.configMap.keySet()){
            System.out.println(line + "  " + detector.configMap.get(line));
        }
        System.out.println("regexp  " + detector.regexMap);
        Set<String> rules = detector.regexMap.keySet();
        for (String regexName : rules){
            String rule = detector.regexMap.get(regexName);
//            System.out.println(regexName +" "+  rule );
        }

        String weblog = "172.19.252.104 - - [09/Sep/2016:17:35:14 +0800] \"GET /scripts/bb_smilies.php?user=MToxOjE6MToxOjE6MToxOjE6Li4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZAAK HTTP/1.1\" 302 154 \"-\" \"Mozilla/4.75 [en] (X11, U; Rsas)\"";
        try{
            detector.MatchRule(weblog);
        }catch (Exception e){
            e.printStackTrace();
        }

    }
}
